package com.ebei.admin.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ebei.admin.common.constant.Constants;
import com.ebei.admin.common.util.CommonUtil;
import com.ebei.admin.common.util.ConvertUtil;
import com.ebei.admin.common.util.TreeUtil;
import com.ebei.admin.mapper.SysUserMapper;
import com.ebei.admin.model.dto.*;
import com.ebei.admin.model.entity.SysCompany;
import com.ebei.admin.model.entity.SysOrgRole;
import com.ebei.admin.model.entity.SysOrgRoleUser;
import com.ebei.admin.model.entity.SysUser;
import com.ebei.admin.service.*;
import com.ebei.common.constant.CommonConstant;
import com.ebei.common.constant.MqQueueConstant;
import com.ebei.common.constant.SecurityConstants;
import com.ebei.common.util.Query;
import com.ebei.common.util.R;
import com.ebei.common.util.Result;
import com.ebei.common.util.template.MobileMsgTemplate;
import com.ebei.common.vo.MenuVO;
import com.ebei.common.vo.UserVO;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.convert.Convert;
import com.xiaoleilu.hutool.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 用户服务实现类
 *
 * @author crazypenguin
 * @version 1.0
 * @created 2018/4/17
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private SysOrgRoleUserService sysOrgRoleUserService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysOrgService sysOrgService;
    @Autowired
    private PositionService positionService;
    @Autowired
    private SysCompanyService sysCompanyService;

    @Override
    public UserInfo findUserInfo(UserVO userVo, Boolean isPc) {
        SysUser condition = new SysUser();
        condition.setUserAccount(userVo.getUserAccount());
        condition.setDelFlag(CommonConstant.STATUS_NORMAL);
        SysUser sysUser = this.selectOne(new EntityWrapper<>(condition));

        UserInfo userInfo = new UserInfo();
        // 用户
        userInfo.setSysUser(sysUser);
        // 菜单
        if (isPc) {
            // 设置菜单
            Map<String, Object> params = new HashMap<>();
            params.put("userId", sysUser.getUserId());
            List<String> deviceTypes = new ArrayList<>();
            deviceTypes.add("0");
            params.put("deviceTypes", deviceTypes);
            List<MenuVO> menuVOS = this.sysMenuService.selectMenuListByUserId(params);
            List<RouterTree> routerTreeList = new ArrayList<>();
            RouterTree routerTree;
            for (MenuVO menuVO : menuVOS) {
                // pc端过滤掉前端name,path,title为空的路由
                if (menuVO.getMenuCode() == null || menuVO.getMenuCode().trim().equals("")) {
                    continue;
                }
                if (menuVO.getUrl() != null && menuVO.getUrl().trim().equals("")) {
                    continue;
                }
                if (menuVO.getMenuName() != null && menuVO.getMenuName().trim().equals("")) {
                    continue;
                }
                routerTree = new RouterTree();
                routerTree.setName(menuVO.getMenuCode());
                routerTree.setPath(menuVO.getUrl());
                routerTree.setTitle(menuVO.getMenuName());
                routerTree.setId(menuVO.getMenuId());
                routerTree.setParentId(menuVO.getParentId());
                routerTreeList.add(routerTree);
            }
            userInfo.setMenuList(TreeUtil.bulid(routerTreeList, null));
        } else {
            Map<String, Object> params = new HashMap<>();
            params.put("userId", sysUser.getUserId());
            List<String> deviceTypes = new ArrayList<>();
            deviceTypes.add("1");
            params.put("deviceTypes", deviceTypes);
            List<MenuVO> menuVOS = this.sysMenuService.selectMenuListByUserId(params);
            List<AppMenuTree> appMenuTrees = new ArrayList<>();
            AppMenuTree appMenuTree;
            for (MenuVO menuVO : menuVOS) {
                appMenuTree = new AppMenuTree();
                appMenuTree.setMenuCode(menuVO.getMenuCode());
                appMenuTree.setMenuName(menuVO.getMenuName());
                appMenuTree.setId(menuVO.getMenuId());
                appMenuTree.setParentId(menuVO.getParentId());
                appMenuTrees.add(appMenuTree);
            }
            userInfo.setAppMenuList(TreeUtil.bulid(appMenuTrees, null));

            // app额外补充岗位信息
            SysOrgRoleUser condition1 = new SysOrgRoleUser();
            condition1.setUserId(sysUser.getUserId());
            List<SysOrgRoleUser> sysOrgRoleUserList = sysOrgRoleUserService.selectList(new EntityWrapper<>(condition1));
            Set<SysOrgRole> positionList = new HashSet<>();
            for(SysOrgRoleUser sysOrgRoleUser : sysOrgRoleUserList){
                SysOrgRole sysOrgRole = positionService.selectById(sysOrgRoleUser.getPositionId());
                positionList.add(sysOrgRole);
            }
            List<SysOrgRole> positionResultList = new ArrayList<>();
            positionResultList.addAll(positionList);
            userInfo.setPositionList(positionResultList);
        }

        UserSupplyForApp userSupplyForApp = new UserSupplyForApp();
        // 获取人员所属组织的名称
        if (sysUser.getOrgId() != null && !"".equals(sysUser.getOrgId())) {
            userSupplyForApp.setOrgName(sysOrgService.selectById(sysUser.getOrgId()).getName());
            userInfo.setUserSupplyForApp(userSupplyForApp);
        }
        // 企业人员 返回是否是保密企业字段
        if(Constants.TYPE_COM.equals(sysUser.getType())){
            SysCompany sysCompany = sysCompanyService.selectById(sysUser.getOrgId());
            userSupplyForApp.setIsSceretCompany("0".equals(sysCompany.getIsSecret()));
        }

        // 获取角色列表
        List<RoleDTO> roleList = sysRoleService.getRoleByUserIdAndRoleCode(sysUser.getUserId(), null);
        userInfo.setRoleList(roleList);
        // 设置是否是超级管理员
        userInfo.setIsSuperAdmin(sysRoleService.hasPermission(sysUser.getUserId(), Constants.SUPER_ADMIN));

        return userInfo;
    }

    @Override
    public UserVO findUserByUserAccount(String userAccount) {
        return sysUserMapper.selectUserByUserAccount(userAccount);
    }

    /**
     * 通过手机号查询用户信息
     *
     * @param mobile 手机号
     * @return 用户信息
     */
    @Override
    @Cacheable(value = "user_details_mobile", key = "#mobile")
    public UserVO findUserByMobile(String mobile) {
        return sysUserMapper.selectUserVoByMobile(mobile);
    }

    /**
     * 通过openId查询用户
     *
     * @param openId openId
     * @return 用户信息
     */
    @Override
    @Cacheable(value = "user_details_openid", key = "#openId")
    public UserVO findUserByOpenId(String openId) {
        return sysUserMapper.selectUserVoByOpenId(openId);
    }

   /* @Override
    public Page selectWithRolePage(Query query) {
        DataScope dataScope = new DataScope();
        dataScope.setScopeName("deptId");
        dataScope.setIsOnly(true);
        // dataScope.setDeptIds(getChildDepts());
        dataScope.putAll(query.getCondition());
        query.setRecords(sysUserMapper.selectUserVoPageDataScope(query, dataScope));
        return query;
    }*/

    /**
     * 通过ID查询用户信息
     *
     * @param id 用户ID
     * @return 用户信息
     */
    @Override
    public UserVO selectUserVoById(Integer id) {
        //根据人员的id初始化右边的数据
        return sysUserMapper.selectUserVoById(id);
    }

    @Override
    public List<Map<String,Object>> findUsersByRoleCondition(Map<String, Object> params) {
        return sysUserMapper.findUsersByRoleCondition(params);
    }

    /**
     * 保存用户验证码，和randomStr绑定
     *
     * @param randomStr 客户端生成
     * @param imageCode 验证码信息
     */
    @Override
    public void saveImageCode(String randomStr, String imageCode) {
        redisTemplate.opsForValue().set(SecurityConstants.DEFAULT_CODE_KEY + randomStr, imageCode, SecurityConstants.DEFAULT_IMAGE_EXPIRE, TimeUnit.SECONDS);
    }

    /**
     * 发送验证码
     * <p>
     * 1. 先去redis 查询是否 60S内已经发送
     * 2. 未发送： 判断手机号是否存 ? false :产生4位数字  手机号-验证码
     * 3. 发往消息中心-》发送信息
     * 4. 保存redis
     *
     * @param mobile 手机号
     * @return true、false
     */
    @Override
    public R<Boolean> sendSmsCode(String mobile) {
        Object tempCode = redisTemplate.opsForValue().get(SecurityConstants.DEFAULT_CODE_KEY + mobile);
        if (tempCode != null) {
            log.error("用户:{}验证码未失效{}", mobile, tempCode);
            return new R<>(false, "验证码未失效，请失效后再次申请");
        }

        SysUser params = new SysUser();
        params.setTelephone(mobile);
        List<SysUser> userList = this.selectList(new EntityWrapper<>(params));

        if (CollectionUtil.isEmpty(userList)) {
            log.error("根据用户手机号{}查询用户为空", mobile);
            return new R<>(false, "手机号不存在");
        }

        String code = RandomUtil.randomNumbers(4);
        log.info("短信发送请求消息中心 -> 手机号:{} -> 验证码：{}", mobile, code);
        rabbitTemplate.convertAndSend(MqQueueConstant.MOBILE_CODE_QUEUE, new MobileMsgTemplate(mobile, code, CommonConstant.ALIYUN_SMS));
        redisTemplate.opsForValue().set(SecurityConstants.DEFAULT_CODE_KEY + mobile, code, SecurityConstants.DEFAULT_IMAGE_EXPIRE, TimeUnit.SECONDS);
        return new R<>(true);
    }

    /**
     * 删除用户
     *
     * @param sysUser 用户
     * @return Boolean
     */
    @Override
    // @CacheEvict(value = "user_details", key = "#sysUser.userName")
    public Boolean deleteUserById(SysUser sysUser) {
        this.deleteById(sysUser.getUserId());
        return Boolean.TRUE;
    }

    @Override
    //@CacheEvict(value = "user_details", key = "#username")
    public Boolean updateUserInfo(UserDTO userDto, String username) {
        UserVO userVo = this.findUserByUserAccount(username);
        SysUser sysUser = new SysUser();
        if (ENCODER.matches(userDto.getPassword(), userVo.getPassword())) {
            sysUser.setPassword(ENCODER.encode(userDto.getNewPassword()));
        }
        sysUser.setUserId(userVo.getUserId());
        sysUser.setAvatar(userDto.getAvatar());

        return this.updateById(sysUser);
    }

    @Override
    // @CacheEvict(value = "user_details", key = "#username")
    public Result updateUser(Map<String, Object> map, String username) throws Exception {
        SysUser sysUser = (SysUser) ConvertUtil.mapToObject(map, SysUser.class);
        sysUser.setUpdateTime(new Date());
        SysUser original = sysUserMapper.selectById(sysUser.getUserId());
        if (!sysUser.getPassword().equals(original.getPassword())) {
            sysUser.setPassword(CommonUtil.ENCODER.encode(sysUser.getPassword()));
        }
        sysUserMapper.updateById(sysUser);

        return new Result(sysUserMapper.selectUserVoById(sysUser.getUserId()), Result.SUCCESS);
    }

    @Override
    public Boolean insertByList(List<Map<String, Object>> list) throws Exception {
        List param = ConvertUtil.convertList(list, SysUser.class);
        return insertBatch(param);
    }

    @Override
    public Result<Page> findByParam(Map<String, Object> map) {
        // 必须传orgId(园区或者公司的id)
        if(map.get("orgId") == null){
            return new Result<>(Result.FAIL,"请选择组织");
        }
        // 排除已经关联岗位的人员
        if (StringUtils.hasLength(Convert.toStr(map.get("positionId")))) {
            EntityWrapper ew = new EntityWrapper<>();
            ew.eq("position_id", Convert.toStr(map.get("positionId")));
            List<SysOrgRoleUser> roleList = sysOrgRoleUserService.selectList(ew);
            map.put("list", roleList);
        }
        Query query = new Query(map);
        query.setRecords(sysUserMapper.findByParam(query, query.getCondition()));
        return new Result(query, Result.SUCCESS);
    }

    @Override
    public Result lock(Integer id) {
        SysUser sysUser = sysUserMapper.selectById(id);
        sysUser.setDelFlag(CommonConstant.STATUS_LOCK);
        sysUserMapper.updateById(sysUser);
        return Result.OK;
    }

    @Override
    public Result findUserByOrgId(Integer orgId) {
        if (orgId == null) {
            return new Result(null, Result.FAIL, "组织id不能为空");
        }
        Map<String, Object> params = new HashMap<>();
        params.put("delFlag", CommonConstant.STATUS_NORMAL);
        params.put("orgId", orgId);
        List<SysUser> userList = sysUserMapper.findUserByOrgId(params);

        return new Result(userList, Result.SUCCESS, "获取成功");
    }

    @Override
    public Result<Page> getUsersForDevice(Map<String, Object> params) {
        try {
            Query query = new Query(params);
            query.setRecords(sysUserMapper.getUsersForDevice(query, query.getCondition()));
            return new Result(query, Result.SUCCESS, "获取成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result<>(Result.FAIL, "系统错误");
        }
    }

}
